package com.show.mybatis.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Configuration {
    private String driver;
    private String url;
    private String username;
    private String password;

    private Map<String,Mapper> mappers = new HashMap<>();

    private ComboPooledDataSource ds;

    private static Configuration config;

    public static Configuration getInstance(){
        if (config == null){
            return new Configuration();
        }
        return config;
    }

    public Configuration() {
        sqlMapConfigLoad();
    }

    public DataSource createDataSource(){
        try {
            if (ds == null){
                ds = new ComboPooledDataSource();
                ds.setDriverClass(driver);
                ds.setJdbcUrl(url);
                ds.setUser(username);
                ds.setPassword(password);
            }
            return ds;
        } catch (PropertyVetoException e) {
            e.printStackTrace();
            return null;
        }
    }

    public void sqlMapConfigLoad(){

        try {
            InputStream in = this.getClass().getClassLoader().getResourceAsStream("sqlMapConfig.xml");

            SAXReader reader = new SAXReader();

            Document doc = reader.read(in);

            Element root = doc.getRootElement();

            List<Element> propertyList = root.selectNodes("//property");

            for (Element proEle : propertyList) {
                String name = proEle.attributeValue("name");

                String value = proEle.attributeValue("value");

                if ("driver".equals(name)){
                    this.driver = value;
                }else if ("url".equals(name)){
                    this.url = value;
                }else if ("username".equals(name)){
                    this.username = value;
                }else if ("password".equals(name)){
                    this.password = value;
                }
            }

            List<Element> mapperList = root.selectNodes("//mapper");

            for (Element mapeEle : mapperList) {
                String resource = mapeEle.attributeValue("resource");

                mapperConfigLoad(resource);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    private void mapperConfigLoad(String resource) {
        try {
            InputStream in = this.getClass().getClassLoader().getResourceAsStream(resource);

            SAXReader saxReader = new SAXReader();

            Document doc = saxReader.read(in);

            Element root = doc.getRootElement();

            String nameSpace = root.attributeValue("namespace");

            List<Element> selectList = root.selectNodes("//select");

            for (Element selEle : selectList) {
                String id = selEle.attributeValue("id");

                String resultType = selEle.attributeValue("resultType");

                String queryString = selEle.getTextTrim();

                Mapper mapper = new Mapper();

                mapper.setNameSpace(nameSpace);
                mapper.setId(id);
                mapper.setResultType(resultType);
                mapper.setQueryString(queryString);

                mappers.put(nameSpace + "." + id,mapper);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Map<String, Mapper> getMappers() {
        return mappers;
    }

    public void setMappers(Map<String, Mapper> mappers) {
        this.mappers = mappers;
    }


    public ComboPooledDataSource getDs() {
        return ds;
    }

    public void setDs(ComboPooledDataSource ds) {
        this.ds = ds;
    }

}
